package cn.edu.ctgu;

/**.
 * YesterDate 类用于计算给定日期的前一天日期，同时提供日期有效性检查和闰年判断功能。
 */
public final class YesterDate {

    // 定义常量以避免魔法数字
    private static final int MIN_YEAR = 1900;
    private static final int MAX_YEAR = 2050;
    private static final int MONTHS_IN_YEAR = 12;
    private static final int FEBRUARY = 2;
    private static final int DAYS_IN_FEBRUARY_COMMON_YEAR = 28;
    private static final int DAYS_IN_FEBRUARY_LEAP_YEAR = 29;
    private static final int DAYS_IN_SMALL_MONTH = 30;
    private static final int DAYS_IN_BIG_MONTH = 31;
    private static final int DIVISIBLE_BY_FOUR = 4;
    private static final int DIVISIBLE_BY_HUNDRED = 100;
    private static final int DIVISIBLE_BY_FOUR_HUNDRED = 400;
    private static final int JANUARY = 1;
    private static final int MARCH = 3;
    private static final int MAY = 5;
    private static final int JULY = 7;
    private static final int AUGUST = 8;
    private static final int OCTOBER = 10;
    private static final int DECEMBER = 12;
    private static final int APRIL = 4;
    private static final int JUNE = 6;
    private static final int SEPTEMBER = 9;
    private static final int NOVEMBER = 11;

    /**.
     * 私有构造函数，防止实例化工具类。
     */
    private YesterDate() {
        // 防止实例化
    }

    /**.
     * 获取给定日期的前一天日期。
     *
     * @param year  年份
     * @param month 月份
     * @param day   日期
     * @return 前一天的日期，格式为 "年, 月, 日"，若输入无效则返回 "提示输入错误"
     */
    public static String getPreviousDate(int year, int month, int day) {
        if (!isValidDay(year, month, day)) {
            return "提示输入错误";
        }

        // 输入有效性检查
        if (year < MIN_YEAR || year > MAX_YEAR || day < 1) {
            return "提示输入错误";
        }

        return calculatePreviousDate(year, month, day);
    }

    private static String calculatePreviousDate(int year, int month, int day) {
        int prevYear = year;
        int prevMonth = month;
        int prevDay = day - 1;

        if (prevDay == 0) {
            prevMonth--;
            if (prevMonth == 0) {
                prevMonth = MONTHS_IN_YEAR;
                prevYear--;
            }
            // 根据月份设置前一天日期
            if (prevMonth == FEBRUARY) {
                boolean isLeap = isLeapYear(prevYear);
                if (isLeap) {
                    prevDay = DAYS_IN_FEBRUARY_LEAP_YEAR;
                } else {
                    prevDay = DAYS_IN_FEBRUARY_COMMON_YEAR;
                }
            } else if (prevMonth == APRIL
                    || prevMonth == JUNE
                    || prevMonth == SEPTEMBER
                    || prevMonth == NOVEMBER) {
                prevDay = DAYS_IN_SMALL_MONTH;
            } else {
                prevDay = DAYS_IN_BIG_MONTH;
            }
        }
        return prevYear + ", " + prevMonth + ", " + prevDay;
    }

    /**.
     * 判断给定年份是否为闰年。
     *
     * @param year 待判断的年份
     * @return 如果是闰年返回 true，否则返回 false
     */
    private static boolean isLeapYear(int year) {
        return (year % DIVISIBLE_BY_FOUR == 0 && year % DIVISIBLE_BY_HUNDRED != 0)
                || (year % DIVISIBLE_BY_FOUR_HUNDRED == 0);
    }

    /**.
     * 检查给定日期是否有效。
     *
     * @param year  年份
     * @param month 月份
     * @param day   日期
     * @return 如果日期有效返回 true，否则返回 false
     */
    private static boolean isValidDay(int year, int month, int day) {
        switch (month) {
            case JANUARY:
            case MARCH:
            case MAY:
            case JULY:
            case AUGUST:
            case OCTOBER:
            case DECEMBER:
                return day <= DAYS_IN_BIG_MONTH;
            case APRIL:
            case JUNE:
            case SEPTEMBER:
            case NOVEMBER:
                return day <= DAYS_IN_SMALL_MONTH;
            case FEBRUARY:
                boolean isLeap = isLeapYear(year);
                if (isLeap) {
                    return day <= DAYS_IN_FEBRUARY_LEAP_YEAR;
                } else {
                    return day <= DAYS_IN_FEBRUARY_COMMON_YEAR;
                }
            default:
                return false;
        }
    }
}